home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / admin / chkbackup < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  7.5 KB  |  265 lines

  1. #!/bin/ksh
  2. # @(#) chkbackup.ksh 2.1 96/06/21
  3. # 95/05/28 john h. dubois iii (john@armory.com)
  4. # 95/06/26 Added all options.
  5. # 96/04/08 Try /dev/nrStp0 in addition to /dev/nrct0.  Added t option.
  6. # 96/06/16 Added uN options.
  7. # 96/06/21 Write status to logfile.  Added L option.  Print tape amount info.
  8.  
  9. # Usage: mkfiles name ...
  10. # Creates the named files with some attempt at security.
  11. # This will be more reliable if user do not have chown authority.
  12. # Any file that contains no / characters is created in the user's tempdir.
  13. # If TMP was not set, it is set by this function (but not exported).
  14. # Returns 0 on success; prints a diagnostic message & returns 1 on failure.
  15. function mkfiles {
  16.     typeset file files
  17.     typeset -i i=0
  18.  
  19.     : ${TMP:=$TMPDIR}
  20.     : ${TMP:=/tmp}
  21.     for file; do
  22.     [[ "$file" != */* ]] && file="$TMP/$file"
  23.     files[i]=$file
  24.     let i+=1
  25.     done
  26.     set -- "${files[@]}"
  27.  
  28.     rm -f "$@" || {
  29.     # hopefully rm will have printed a more specific message.
  30.     print -r -u2 "Could not remove pre-existing files."
  31.     return 1
  32.     }
  33.     for file; do
  34.     # Use >> to avoid 0'ing the file in case a symlink was just made from
  35.     # the filename to something we don't want to truncate
  36.     >> "$file" || {
  37.         print -r -u2 "Could not create temp file $file"
  38.         return 1
  39.     }
  40.     # These are very suspicious
  41.     [ -s "$file" ] && {
  42.         print -r -u2 "New tempfile is not empty!!!"
  43.         return 1
  44.     }
  45.     [ -O "$file" ] || {
  46.         print -r -u2 "Do not own $file!!!"
  47.         return 1
  48.     }
  49.     done
  50.     # Could do some more stuff here, but anyone concerned with security should
  51.     # have chown authorization off for most users.
  52.     return 0
  53. }
  54.  
  55. # Usage: mktempfile name
  56. # Creates a tempfile name tempdir/#name$$, and sets the global mktempfile_ret
  57. # to that name.  tempdir is a temp directory in $TMP, $TMPDIR, or /tmp, and $$
  58. # is the PID of the current process.
  59. # name should be 8 characters or less, so that the resulting filename will
  60. # not be more than 14 characters long (a limit on some machines).
  61. # Returns 0 on success, prints a diagnostic message & returns 1 on failure.
  62. function mktempfile {
  63.     typeset file="#$1$$"
  64.     mkfiles "$file"
  65.     mktempfile_ret="$TMP/#$1$$"
  66. }
  67.  
  68. function lprint {
  69.     print -r -- "$*"
  70.     $log && print -r -- "$*" >> "$logfile"
  71. }
  72.  
  73. function Rewind {
  74.     if $rewind; then
  75.     print -r "*** Rewinding..."
  76.     tape rewind $nr_device || {
  77.         print -ru2 -- "$longname: Rewind of $nr_device failed.  Exiting."
  78.         exit 1
  79.     }
  80.     fi
  81. }
  82.  
  83. function check {
  84.     typeset -i status
  85.  
  86.     let extent+=1
  87.     lprint "*** `date`  Checking extent $extent"
  88.     $debug && set -x
  89.     if [ -n "$Uncompress" ]; then
  90.     nice -n $nice $Uncompress | nice -$nice "${cmd[@]}"
  91.     else
  92.     nice -n $nice "${cmd[@]}"
  93.     fi < $nr_device >&3
  94.     status=$?
  95.     $debug && set +x
  96.     return $status
  97. }
  98.  
  99. nr_device1=/dev/nrct0
  100. nr_device2=/dev/nrStp0
  101. nr_device=
  102. longname=${0##*/}
  103. rewind=true
  104. debug=false
  105. log=true
  106. defaultCommand="cpio -it -C 65536"
  107. def_nice=15
  108. typeset -i nice=$def_nice
  109. typeset -i maxExtent=0
  110. Usage=\
  111. "Usage: $longname [-hLnv] [-e<extents>] [-d<device>] [-u<uncompress-command>]
  112.        [archive listing command]"
  113. exec 3>/dev/null    # default dest for file lists
  114.  
  115. while getopts :hLnN:e:d:vxu: opt; do
  116.     case $opt in
  117.     h)
  118.     print -r -- \
  119. "$longname: Check tape backups.
  120. $Usage
  121. $longname reads all of the file extents (tape sections between filemarks) on a
  122. tape and passes them through a command to test the archive integrity of each
  123. backup.  The default command is \"$defaultCommand\".  An alternate command can
  124. be given at the end of the command line that $longname is invoked with.  It
  125. will be run for each file extent in turn, with the tape device passed as its
  126. input and it standard output (which would typically be a listing of the
  127. archive) discarded so that only errors will be displayed.  The archive listing
  128. command should not actually extract files onto disk.  The command will be
  129. repeatedly invoked, either as many times as specified with the -e option (if
  130. given) or until it exits nonzero, whichever comes first.  If -e is not given,
  131. the report produced by $longname should give a good status for the number of
  132. archives stored on the tape, and then one failure when it tries to read beyond
  133. the end of the last position on the tape that has been written to.  
  134. For each extent successfully read, a status line and a report of the amount of
  135. data read from tape is printed.  The same information is written to a logfile
  136. named /tmp/#chkback.pid, where pid is the process ID of the program.  To get
  137. the tape amount information, the tape control device is used.  The name of the
  138. control device is determined by replacing everything up through a leading 'r'
  139. in the trailing component of the device name with 'x'.  For example, the
  140. control device for /dev/nrStp0 would be /dev/xStp0.
  141. Options:
  142. -h: Print this help.
  143. -n: Do not rewind the tape device before or after checking the backups.
  144. -e<extents>: Check only the number of extents specified.
  145. -d<device>: Use <device> instead of the default of $nr_device1 or (if it does
  146.     not exist) $nr_device2.  <device> should be a no-rewind device.
  147. -L: Do not create or write to the logfile.
  148. -N<nice-increment>: Use <nice-increment> when running uncompressing and archive
  149.     listing commands.  The default is $def_nice.
  150. -u<uncompress-command>: Pass the archive data through <uncompress-command>
  151.     before giving it to the archiving listing command.  This could also be done
  152.     by making the uncompress-command part of the archive listing command.
  153.     However, if the default archive listing command is correct, using -u avoids
  154.     the need to give the archive listing command explicitly.
  155. -v: Verbose.  Print files found."
  156.     exit 0
  157.     ;;
  158.     N)
  159.     nice=$OPTARG || exit 1
  160.     ;;
  161.     n)
  162.     rewind=false
  163.     ;;
  164.     d)
  165.     nr_device=$OPTARG
  166.     [[ "$nr_device" != */* ]] && nr_device=/dev/$nr_device
  167.     ;;
  168.     e)
  169.     maxExtent=$OPTARG || {
  170.         print -ru2 -- "$longname: Bad number given with -e.  Exiting."
  171.         exit 1
  172.     }
  173.     ;;
  174.     u)
  175.     Uncompress=$OPTARG
  176.     ;;
  177.     L)
  178.     log=false;;
  179.     v)
  180.     exec 3>&1
  181.     ;;
  182.     x)
  183.     debug=true
  184.     ;;
  185.     +?)
  186.     print -ru2 -- "$longname: options should not be preceded by a '+'."
  187.     exit 1
  188.     ;;
  189.     :)
  190.         print -r -u2 -- \
  191.         "$longname: Option '$OPTARG' requires a value.  Use -h for help."
  192.         exit 1
  193.         ;;
  194.     ?) 
  195.     print -ru2 -- "$longname: $OPTARG: bad option.  Use -h for help."
  196.     exit 1
  197.     ;;
  198.     esac
  199. done
  200.  
  201. # remove args that were options
  202. let OPTIND=OPTIND-1
  203. shift $OPTIND
  204.  
  205. if [ $# -lt 1 ]; then
  206.     set -A cmd $defaultCommand
  207. else
  208.     set -A cmd "$@"
  209. fi
  210.  
  211. # Find which device to use
  212. if [ -z "$nr_device" ]; then
  213.     if [ -c $nr_device1 ]; then
  214.     nr_device=$nr_device1
  215.     elif [ -c $nr_device2 ]; then
  216.     nr_device=$nr_device2
  217.     else
  218.     print -ru2 -- \
  219.     "$longname: Neither $nr_device1 nor $nr_device2 exists.  Exiting."
  220.     exit 1
  221.     fi
  222. elif [ ! -c "$nr_device" ]; then
  223.     print -ru2 -- \
  224.     "$longname: $nr_device does not exist or is not a tape device.  Exiting."
  225.     exit 1
  226. fi
  227.  
  228. tail=${nr_device##*/}
  229. xdev="${nr_device%/*}/x${tail#*r}"
  230. if [ ! -c "$xdev" ]; then
  231.     print -ru2 -- \
  232.     "$longname: Cannot access control device $xdev; skipping tape amounts."
  233.     unset xdev
  234. fi
  235.  
  236. if $debug; then
  237.     if [ -n "$xdev" ]; then
  238.     print -ru2 "Using device $nr_device and control device $xdev"
  239.     else
  240.     print -ru2 "Using device $nr_device"
  241.     fi
  242. fi
  243.  
  244. typeset -i extent=0
  245.  
  246. Rewind
  247.  
  248. if $log; then
  249.     TMP=/tmp    # for mkfiles
  250.     mktempfile chkback. || {
  251.     print -ru2 -- "$longname: exiting."
  252.     exit 1
  253.     }
  254.     logfile=$mktempfile_ret
  255.     print -r -- "Writing status information to log file $logfile"
  256. fi
  257.  
  258. while [ maxExtent -eq 0 -o extent -lt maxExtent ] && check; do
  259.     [ -n "$xdev" ] && lprint "$(tape amount "$xdev")"
  260.     lprint "*** `date`  Extent $extent OK"
  261.     sleep 5
  262. done
  263.  
  264. Rewind
  265.